package com.ruoyi.coupons.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.coupons.domain.MemberCoupon;
import com.ruoyi.coupons.service.CouponService;
import com.ruoyi.coupons.service.MemberCouponService;
import com.ruoyi.coupons.mapper.MemberCouponMapper;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
* @author a'su's
* @description 针对表【member_coupon】的数据库操作Service实现
* @createDate 2025-03-18 11:06:04
*/
@Service
public class MemberCouponServiceImpl extends ServiceImpl<MemberCouponMapper, MemberCoupon>
    implements MemberCouponService{

    @Autowired
    @Qualifier("couponRedisTemplate")
    RedisTemplate<String,Object> redisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    private MemberCouponMapper memberCouponMapper;
    @Autowired
    private CouponService couponService;

    private static final String LUA_SCRIPT = "local stockKey = KEYS[1] " +
            "local userLimitKey = KEYS[2] " +
            "local requestKey = 'coupon:request:' .. ARGV[1] " +
            "local userId = ARGV[1] " +
            "local limit = tonumber(ARGV[2]) or 0 " +
            "local requestCount = tonumber(ARGV[3]) or 1 " +
            "local current = tonumber(redis.call('INCR', requestKey)) " +
            "if current == 1 then redis.call('EXPIRE', requestKey, 5) end " +
            "if current > 10 then return -2 end " +
            "local userCount = tonumber(redis.call('GET', userLimitKey) or '0') " +
            "if userCount + requestCount > limit then return -1 end " +
            "local stock = tonumber(redis.call('GET', stockKey) or '0') " +
            "if stock < requestCount then return 0 end " +
            "redis.call('DECRBY', stockKey, requestCount) " +
            "redis.call('INCRBY', userLimitKey, requestCount) " +
            "return 1 ";
    @Override
    public List<MemberCoupon> getList(int memberId,int couponStatus) {
        return memberCouponMapper.getList(memberId,couponStatus);
    }

    @Override
    public int getNum(int memberId) {
        try{
            return memberCouponMapper.getNum(memberId).getNumber();
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }

    }

    @Override
    public MemberCoupon getMemberCoupon(MemberCoupon memberCoupon) {

        return memberCouponMapper.getMemberCoupon(memberCoupon);
    }

    @Override
    @Transactional
    public MemberCoupon lingqu(int couponId,int memberId,int requestCount) {

        //获得领取优惠券的限领数量
        int limit = couponService.getLimit(couponId);
        System.out.println(limit);
        //优惠券库存
        String stockKey = "coupon:stock:" + couponId;
        //用户已领取记录
        String userLimitKey = "coupon:user:" + memberId + ":" + couponId;
        // 删除原有初始化逻辑，改为每次查询数据库
        int stock = couponService.getStock(couponId);
        redisTemplate.opsForValue().set(stockKey, String.valueOf(stock));
//        int nowNumber=memberCouponMapper.getNumberCoupon(memberId,couponId).getNumber();
//        redisTemplate.opsForValue().set(userLimitKey,nowNumber);
        Long result = redisTemplate.execute(new DefaultRedisScript<>(LUA_SCRIPT,Long.class), Arrays.asList(stockKey,userLimitKey),String.valueOf(memberId),String.valueOf(limit),String.valueOf(requestCount));


        if (result == 1) {
            MemberCoupon memberCoupon = new MemberCoupon();
            memberCoupon.setMemberId(memberId);
            memberCoupon.setCouponId(couponId);
            memberCoupon.setNumber(1);
            memberCoupon.setCouponStatus(0);
            System.out.println("给队列发送信息");
            rabbitTemplate.convertAndSend("couponExchange", "a", memberCoupon);
            return memberCoupon;
        } else if (result == -1) {
            throw new RuntimeException("领取失败，超出限领数量");
        } else if (result == -2) {
            throw new RuntimeException("请求过于频繁，请稍后再试");
        } else {
            throw new RuntimeException("优惠券已抢完");
        }
    }

    @Override
    public int updateNum(int mcId,int limit) {
        return memberCouponMapper.updateNum(mcId,limit);
    }
}